package com.pets.util;

import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.methods.*;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.util.StringUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * https工具类
 */
public class HttpsUtil {

    private static CloseableHttpClient client;

    static {
        try {
            // 采用绕过验证的方式处理https请求
            SSLContext sslcontext = createIgnoreVerifySSL();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext);
            // 设置协议http和https对应的处理socket链接工厂的对象
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE).register("https", sslsf).build();
            PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
                    socketFactoryRegistry);
            HttpClients.custom().setConnectionManager(connManager);
            // 创建自定义的httpclient对象
            client = HttpClients.custom().setConnectionManager(connManager).setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

    }


    /**
     * 发送https请求
     *
     * @param url
     *            请求地址
     * @param param
     *            参数
     * @param method
     *            请求的方法类型
     * @param headerMap
     *            请求头map
     * @return 响应信息
     */
    public static String sendHttpsRequest(String url, String param, String method,  Map<String, String> headerMap) {
        method = method.toUpperCase();
        switch (method) {
            case "GET":
                HttpGet get = new HttpGet(url);
                return JSON.toJSONString(execute(get, headerMap));
            case "POST":
                HttpPost post = new HttpPost(url);
                // 判断是否有参数
                if (!StringUtils.isEmpty(param)) {
                    // 构建消息实体
                    StringEntity message = new StringEntity(param, Charset.forName("UTF-8"));
                    message.setContentEncoding("UTF-8");
                    // 发送Json格式的数据请求
                    message.setContentType("application/json");
                    post.setEntity(message);
                }
                return JSON.toJSONString(execute(post, headerMap));
            case "PUT":
                HttpPut put = new HttpPut(url);
                // 判断是否有参数
                if (!StringUtils.isEmpty(param)) {
                    // 构建消息实体
                    StringEntity message = new StringEntity(param, Charset.forName("UTF-8"));
                    message.setContentEncoding("UTF-8");
                    // 发送Json格式的数据请求
                    message.setContentType("application/json");
                    put.setEntity(message);
                }
                return JSON.toJSONString(execute(put, headerMap));
            case "PATCH":
                HttpPatch patch = new HttpPatch(url);
                // 判断是否有参数
                if (!StringUtils.isEmpty(param)) {
                    // 构建消息实体
                    StringEntity message = new StringEntity(param, Charset.forName("UTF-8"));
                    message.setContentEncoding("UTF-8");
                    // 发送Json格式的数据请求
                    message.setContentType("application/json");
                    patch.setEntity(message);
                }
                return JSON.toJSONString(execute(patch, headerMap));
            case "DELETE":
                HttpDelete delete = new HttpDelete(url);
                return JSON.toJSONString(execute(delete, headerMap));
            default:
                Map<String, String> resultMap = new HashMap<>(8);
                resultMap.put("status", "failure");
                resultMap.put("message", "暂不支持的方法类型");
                resultMap.put("result", "");
                return JSON.toJSONString(resultMap);
        }
    }

    /**
     * 发送请求
     *
     * @param request
     *            http请求类型
     * @param headerMap
     * @return 结果集
     */
    private static Map<String, String> execute(HttpUriRequest request, Map<String, String> headerMap) {
        Map<String, String> resultMap = new HashMap<>(8);
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String result = "";
        try {
            // 设置请求头
           /* request.setHeader("Content-type", "application/json");
            request.setHeader("keyId",  authorization);*/
            if (Objects.nonNull(headerMap)) {
                for (Map.Entry<String, String> header : headerMap.entrySet()) {
                    request.setHeader(header.getKey(), header.getValue());
                }
            }
            response = client.execute(request);
            // 获取结果实体
            if (response != null) {
                entity = response.getEntity();
                result = EntityUtils.toString(entity, "UTF-8");
                if (response.getStatusLine().getStatusCode() == 200) {
                    resultMap.put("status", "success");
                    resultMap.put("message", "");
                    resultMap.put("result", result);
                } else {
                    resultMap.put("status", "failure");
                    resultMap.put("message", result);
                    resultMap.put("result", "");
                }
            } else {
                resultMap.put("status", "failure");
                resultMap.put("message", "发送https请求异常，响应信息为空");
                resultMap.put("result", "");
            }
        } catch (ParseException | IOException e) {
            resultMap.put("status", "failure");
            resultMap.put("message", e.getMessage());
            resultMap.put("result", "");
        } finally {
            try {
                EntityUtils.consume(entity);
                //释放链接
                if(response!=null){
                    response.close();
                }
            } catch (IOException e) {
            }
        }
        return resultMap;
    }

    /**
     * 绕过验证
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("SSLv3");

        // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                                           String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                                           String paramString) throws CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sc.init(null, new TrustManager[] { trustManager }, null);
        return sc;
    }

}
